﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NAudio.Wave;

namespace WpfWordsLearner
{
	public sealed class VoiceManager : IDisposable
	{
		private System.Threading.AutoResetEvent m_event = null;
		private NAudio.Wave.IWavePlayer waveOutDevice = null;

		public VoiceManager()
		{
			waveOutDevice = new NAudio.Wave.WaveOut();
			waveOutDevice.PlaybackStopped += new EventHandler(waveOutDevice_PlaybackStopped);
			m_event = new System.Threading.AutoResetEvent(false);
		}

		public void Play(System.IO.Stream mp3File)
		{
			NAudio.Wave.WaveStream mainOutputStream;
			NAudio.Wave.WaveChannel32 volumeStream;

			WaveChannel32 inputStream;
			WaveStream mp3Reader = new Mp3FileReader(mp3File);
			inputStream = new WaveChannel32(mp3Reader);
			volumeStream = inputStream;
			mainOutputStream = volumeStream;

			waveOutDevice.Init(mainOutputStream);

			waveOutDevice.Play();

			//Wait while palyback voice playing will be completed
			m_event.WaitOne(TimeSpan.FromSeconds(3));

			if (waveOutDevice != null)
			{
				waveOutDevice.Stop();
			}
			if (mainOutputStream != null)
			{
				// this one really closes the file and ACM conversion
				volumeStream.Close();
				volumeStream = null;
				// this one does the metering stream
				mainOutputStream.Close();
				mainOutputStream = null;
			}
		}

		public void Play(byte[] data)
		{
			NAudio.Wave.WaveStream mainOutputStream;
			NAudio.Wave.WaveChannel32 volumeStream;

			WaveChannel32 inputStream;

			System.IO.Stream mp3File = new System.IO.MemoryStream(data);

			System.IO.Stream sr = new System.IO.MemoryStream();
			mp3File.CopyTo(sr);

			WaveStream mp3Reader = new Mp3FileReader(sr);
			inputStream = new WaveChannel32(mp3Reader);
			volumeStream = inputStream;
			mainOutputStream = volumeStream;

			waveOutDevice.Init(mainOutputStream);

			waveOutDevice.Play();

			//Wait while palyback voice playing will be completed
			m_event.WaitOne(TimeSpan.FromSeconds(3));

			if (waveOutDevice != null)
			{
				if (waveOutDevice.PlaybackState == PlaybackState.Playing)
					waveOutDevice.Stop();
			}
			if (mainOutputStream != null)
			{
				// this one really closes the file and ACM conversion
				volumeStream.Close();
				volumeStream = null;
				// this one does the metering stream
				mainOutputStream.Close();
				mainOutputStream = null;
			}
		}

		void waveOutDevice_PlaybackStopped(object sender, EventArgs e)
		{
			m_event.Set();
		}

		public void Dispose()
		{
			if (waveOutDevice != null)
			{
				waveOutDevice.PlaybackStopped -= new EventHandler(waveOutDevice_PlaybackStopped);
				if (waveOutDevice.PlaybackState == PlaybackState.Playing)
					waveOutDevice.Stop();

				waveOutDevice.Dispose();
				waveOutDevice = null;
			}
			if (m_event != null)
			{
				m_event.Reset();
				m_event.Dispose();
			}
		}
	}

	public sealed class VoiceManager2 : IDisposable
	{
		private System.Threading.AutoResetEvent m_event = null;

		public VoiceManager2()
		{
			m_event = new System.Threading.AutoResetEvent(false);
		}

		public void Play(System.IO.Stream mp3File)
		{
			NAudio.Wave.IWavePlayer waveOutDevice;
			NAudio.Wave.WaveStream mainOutputStream;
			NAudio.Wave.WaveChannel32 volumeStream;

			waveOutDevice = new NAudio.Wave.WaveOut();

			WaveChannel32 inputStream;
			WaveStream mp3Reader = new Mp3FileReader(mp3File);
			inputStream = new WaveChannel32(mp3Reader);
			volumeStream = inputStream;
			mainOutputStream = volumeStream;

			waveOutDevice.Init(mainOutputStream);
			waveOutDevice.PlaybackStopped += new EventHandler(waveOutDevice_PlaybackStopped);
			waveOutDevice.Play();
			//wait while palyback is on
			m_event.WaitOne(TimeSpan.FromSeconds(3));

			if (mainOutputStream != null)
			{
				// this one really closes the file and ACM conversion
				volumeStream.Close();
				volumeStream = null;
				// this one does the metering stream
				mainOutputStream.Close();
				mainOutputStream = null;
			}
			if (waveOutDevice != null)
			{
				waveOutDevice.PlaybackStopped -= new EventHandler(waveOutDevice_PlaybackStopped);
				if (waveOutDevice.PlaybackState == PlaybackState.Playing)
					waveOutDevice.Stop();

				waveOutDevice.Dispose();
				waveOutDevice = null;
			}
		}

		void waveOutDevice_PlaybackStopped(object sender, EventArgs e)
		{
			m_event.Set();
		}

		public void Dispose()
		{
			if (m_event != null)
			{
				m_event.Reset();
				m_event.Dispose();
			}
		}
	}

	public sealed class AlvasVoiceManager : IDisposable
	{
		private Alvas.Audio.PlayerEx playEx = null;
		private Alvas.Audio.Mp3Reader wr = null;

		private int pos = 0;
		private int seconds = 5;
		private int len = 0;

		public AlvasVoiceManager()
		{
			playEx = new Alvas.Audio.PlayerEx();
		}

		public void StartPlay(System.IO.Stream _stream)
		{
			if (playEx.State == Alvas.Audio.DeviceState.Paused)
			{
				playEx.ResumePlay();
			}
			else
			{
				pos = 0;
				wr = new Alvas.Audio.Mp3Reader(_stream);
				len = wr.GetDurationInMS() / 1000;
				IntPtr format = wr.ReadFormat();
				playEx.OpenPlayer(format);
				ReadData();
				playEx.StartPlay();
			}
		}

		private void ReadData()
		{
			if (pos <= len)
			{
				byte[] data = wr.ReadData(pos, seconds);
				pos += seconds;
				playEx.AddData(data);
			}
		}

		public void Dispose()
		{
			if (playEx != null)
				this.playEx.Dispose();
			if (wr != null)
				this.wr.Dispose();
		}
	}

}
